using System;
using System.IO;
using System.Text;

namespace id3
{
	internal class FileCommands
	{
		public static void readMP3Tag(ref MP3 paramMP3)
		{
			// Read the 128 byte ID3 tag into a byte array
			FileStream oFileStream;
			oFileStream = new FileStream(paramMP3.fileComplete, FileMode.Open, FileAccess.Read, FileShare.Read, 128);
			byte[] bBuffer = new byte[128];
			oFileStream.Seek(-128, SeekOrigin.End);
			oFileStream.Read(bBuffer, 0, 128);
			oFileStream.Close();

			// Convert the Byte Array to a String
			Encoding instEncoding = Encoding.GetEncoding(1255); // NB: Encoding is an Abstract class
			string id3Tag = instEncoding.GetString(bBuffer);

			// If there is an attched ID3 v1.x TAG then read it 
			if (id3Tag.Substring(0, 3) == "TAG")
			{
				paramMP3.Title = id3Tag.Substring(3, 30).Trim().Replace("\0","");
				paramMP3.Artist = id3Tag.Substring(33, 30).Trim().Replace("\0","");
				paramMP3.Album = id3Tag.Substring(63, 30).Trim().Replace("\0","");
				paramMP3.id3Year = id3Tag.Substring(93, 4).Trim();
				paramMP3.id3Comment = id3Tag.Substring(97, 28).Trim();

				// Get the track number if TAG conforms to ID3 v1.1
				if (id3Tag[125] == 0)
					paramMP3.TrackNumber = bBuffer[126];
				else
					paramMP3.TrackNumber = 0;
				paramMP3.id3Genre = bBuffer[127];
				paramMP3.hasID3Tag = true;
				// ********* IF USED IN ANGER: ENSURE to test for non-numeric year
			}
			else
			{
				// ID3 Tag not found so create an empty TAG in case the user saces later
				paramMP3.Title = "";
				paramMP3.Artist = "";
				paramMP3.Album = "";
				paramMP3.id3Year = "";
				paramMP3.id3Comment = "";
				paramMP3.TrackNumber = 0;
				paramMP3.id3Genre = 0;
				paramMP3.hasID3Tag = false;
			}
		}

		public static void updateMP3Tag(ref MP3 paramMP3)
		{
			// Trim any whitespace
			paramMP3.Title = paramMP3.Title.Trim();
			paramMP3.Artist = paramMP3.Artist.Trim();
			paramMP3.Album = paramMP3.Album.Trim();
			paramMP3.id3Year = paramMP3.id3Year.Trim();
			paramMP3.id3Comment = paramMP3.id3Comment.Trim();

			// Ensure all properties are correct size
			if (paramMP3.Title.Length > 30)
				paramMP3.Title = paramMP3.Title.Substring(0, 30);
			if (paramMP3.Artist.Length > 30)
				paramMP3.Artist = paramMP3.Artist.Substring(0, 30);
			if (paramMP3.Album.Length > 30)
				paramMP3.Album = paramMP3.Album.Substring(0, 30);
			if (paramMP3.id3Year.Length > 4)
				paramMP3.id3Year = paramMP3.id3Year.Substring(0, 4);
			if (paramMP3.id3Comment.Length > 28)
				paramMP3.id3Comment = paramMP3.id3Comment.Substring(0, 28);

			// Build a new ID3 Tag (128 Bytes)
			byte[] tagByteArray = new byte[128];
			for (int i = 0; i < tagByteArray.Length; i++)
				tagByteArray[i] = 0; // Initialise array to nulls

			// Convert the Byte Array to a String
			Encoding instEncoding = new ASCIIEncoding(); // NB: Encoding is an Abstract class // ************ To DO: Make a shared instance of ASCIIEncoding so we don't keep creating/destroying it
			// Copy "TAG" to Array
			byte[] workingByteArray = instEncoding.GetBytes("TAG");
			Array.Copy(workingByteArray, 0, tagByteArray, 0, workingByteArray.Length);
			// Copy Title to Array
			workingByteArray = instEncoding.GetBytes(paramMP3.Title);
			Array.Copy(workingByteArray, 0, tagByteArray, 3, workingByteArray.Length);
			// Copy Artist to Array
			workingByteArray = instEncoding.GetBytes(paramMP3.Artist);
			Array.Copy(workingByteArray, 0, tagByteArray, 33, workingByteArray.Length);
			// Copy Album to Array
			workingByteArray = instEncoding.GetBytes(paramMP3.Album);
			Array.Copy(workingByteArray, 0, tagByteArray, 63, workingByteArray.Length);
			// Copy Year to Array
			workingByteArray = instEncoding.GetBytes(paramMP3.id3Year);
			Array.Copy(workingByteArray, 0, tagByteArray, 93, workingByteArray.Length);
			// Copy Comment to Array
			workingByteArray = instEncoding.GetBytes(paramMP3.id3Comment);
			Array.Copy(workingByteArray, 0, tagByteArray, 97, workingByteArray.Length);
			// Copy Track and Genre to Array
			tagByteArray[126] = paramMP3.TrackNumber;
			tagByteArray[127] = paramMP3.id3Genre;

			// SAVE TO DISK: Replace the final 128 Bytes with our new ID3 tag
			FileStream oFileStream = new FileStream(paramMP3.fileComplete, FileMode.Open);
			if (paramMP3.hasID3Tag)
				oFileStream.Seek(-128, SeekOrigin.End);
			else
				oFileStream.Seek(0, SeekOrigin.End);
			oFileStream.Write(tagByteArray, 0, 128);
			oFileStream.Close();
			paramMP3.hasID3Tag = true;
		}
	}

	internal struct MP3
	{
		public string FilePath;
		public string fileFileName;
		public string fileComplete;
		public bool hasID3Tag;
		public string Title;
		public string Artist;
		public string Album;
		public string id3Year;
		public string id3Comment;
		public byte TrackNumber;
		public byte id3Genre;

		// Required struct constructor
		public MP3(string path, string name)
		{
			FilePath = path;
			fileFileName = name;
			fileComplete = path;
			hasID3Tag = false;
			Title = null;
			Artist = null;
			Album = null;
			id3Year = null;
			id3Comment = null;
			TrackNumber = 0;
			id3Genre = 0;
		}
	}
}